package com.bruce.spring.http.client.factory;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.service.invoker.HttpExchangeAdapter;
import org.springframework.web.service.invoker.HttpServiceProxyFactory;

import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by bruce in 2025/6/21 23:25
 * <p>
 * <a href="https://github.com/spring-projects/spring-framework/issues/35148?notification_referrer_id=NT_kwDOAMytU7QxNzM2MTU4NTA5MToxMzQxMzcxNQ#issuecomment-3031220797">Include MethodParameter[] parameters in HttpRequestValues.Processor</a>
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class ClientFactory {
    private final ConcurrentHashMap<String /*apiClass + clusterTag*/, Object> clients = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, HttpServiceProxyFactory> httpServiceProxyFactoryMap = new ConcurrentHashMap<>();

    private final TargetSelector targetSelector;
    private final RestTemplateAdapterCreator restTemplateAdapterCreator;
    private final RestClientAdapterCreator restClientAdapterCreator;
    private final WebClientAdapterCreator webClientAdapterCreator;

    public <T> T getClient(String clusterTag, Class<T> apiClass) {
        String url = targetSelector.select(clusterTag);
        return getDirectClient(url, apiClass);
    }

    public <T> T getDirectClient(String url, Class<T> apiClass) {
        String key = url + ":" + apiClass.getName();
        Object o = clients.get(key);
        if (o != null) {
            return (T) o;
        }
        Object o1 = clients.computeIfAbsent(key, k -> createClient(apiClass, url));
        return (T) o1;
    }


    private <T> T createClient(Class<T> apiClass, String url) {
        HttpServiceProxyFactory httpServiceProxyFactory = httpServiceProxyFactoryMap.get(url);
        if (httpServiceProxyFactory == null) {
            httpServiceProxyFactory = httpServiceProxyFactoryMap.computeIfAbsent(url, k -> createHttpServiceProxyFactory1(url));
        }
        return httpServiceProxyFactory.createClient(apiClass);
    }

    /**
     * 用Spring对外的方法创建, 不可以控制参数解析器顺序
     */
    private HttpServiceProxyFactory createHttpServiceProxyFactory1(String url) {
        // HttpExchangeAdapter adapter = restClientAdapterCreator.useReactorNettyHttpClient(url);
        HttpExchangeAdapter adapter = restClientAdapterCreator.useJdk9HttpClient(url);
        HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter)
                .customArgumentResolver(new SimpleObjectGetArgumentResolver())
                .build();
        return factory;
    }





}
